package com.gzx.plugin.tjzy.modular.gzxcase.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.json.JSONObject;
import com.alibaba.fastjson2.JSON;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.gzx.plugin.tjzy.modular.allocate.consts.GzxAllocateType;
import com.gzx.plugin.tjzy.modular.allocate.entity.GzxAllocateRecord;
import com.gzx.plugin.tjzy.modular.allocate.service.GzxAllocateRecordDbService;
import com.gzx.plugin.tjzy.modular.caffeine.UserCaffeine;
import com.gzx.plugin.tjzy.modular.complaint.entity.GzxComplaintUser;
import com.gzx.plugin.tjzy.modular.complaint.mapper.GzxComplaintUserMapper;
import com.gzx.plugin.tjzy.modular.debtor.entity.GzxDebtorInfo;
import com.gzx.plugin.tjzy.modular.debtor.service.GzxDebtorInfoService;
import com.gzx.plugin.tjzy.modular.district.entity.GzxRegionDistrict;
import com.gzx.plugin.tjzy.modular.district.service.GzxRegionDistrictListService;
import com.gzx.plugin.tjzy.modular.gzxcase.bo.GzxCaseDetailQueryBo;
import com.gzx.plugin.tjzy.modular.gzxcase.bo.GzxCaseEditBo;
import com.gzx.plugin.tjzy.modular.gzxcase.bo.GzxCaseQueryBo;
import com.gzx.plugin.tjzy.modular.gzxcase.bo.GzxChangeCaseBo;
import com.gzx.plugin.tjzy.modular.gzxcase.entity.GzxCase;
import com.gzx.plugin.tjzy.modular.gzxcase.entity.GzxCaseDetail;
import com.gzx.plugin.tjzy.modular.gzxcase.service.GzxCaseDbService;
import com.gzx.plugin.tjzy.modular.gzxcase.service.GzxCaseService;
import com.gzx.plugin.tjzy.modular.gzxcase.vo.GzxCaseDetailJsonVo;
import com.gzx.plugin.tjzy.modular.gzxcase.vo.GzxCaseDetailVo;
import com.gzx.plugin.tjzy.modular.gzxcase.vo.GzxCaseExcelVo;
import com.gzx.plugin.tjzy.modular.gzxcase.vo.GzxCaseVo;
import com.gzx.plugin.tjzy.modular.liaison.entity.GzxDebtorLiaison;
import com.gzx.plugin.tjzy.modular.liaison.entity.vo.GzxDebtorLiaisonExcelVo;
import com.gzx.plugin.tjzy.modular.liaison.service.GzxDebtorLiaisonService;
import com.gzx.plugin.tjzy.modular.project.entity.bo.GzxProjectTileBo;
import com.gzx.plugin.tjzy.modular.project.service.GzxProjectService;
import com.gzx.plugin.tjzy.modular.word.mediation.vo.GzxWordMediationVo;
import com.gzx.plugin.tjzy.modular.work.entity.GzxMediatorWork;
import com.gzx.plugin.tjzy.modular.work.entity.vo.GzxMediatorWorkVo;
import com.gzx.plugin.tjzy.modular.work.mapper.GzxMediatorWorkMapper;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import vip.xiaonuo.auth.core.pojo.SaBaseLoginUser;
import vip.xiaonuo.auth.core.util.StpLoginUserUtil;
import vip.xiaonuo.common.consts.BatchNumberConstant;
import vip.xiaonuo.common.exception.CommonException;
import vip.xiaonuo.common.tenant.TenantContext;
import vip.xiaonuo.common.util.*;
import vip.xiaonuo.common.util.CommonWechatUtil;
import vip.xiaonuo.common.wechat.enums.WechatNotificationType;

import java.io.IOException;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * @author zjt
 * @description
 * @date 2024/12/3 14:14
 */
@Slf4j
@Service
@DS("tjzy")
@RequiredArgsConstructor
public class GzxCaseServiceImpl implements GzxCaseService {

    private final GzxCaseDbService caseDbService;

    private final GzxMediatorWorkMapper mediatorWorkMapper;

    private final GzxComplaintUserMapper complaintUserMapper;

    private final GzxDebtorInfoService debtorInfoService;

    private final GzxDebtorLiaisonService debtorLiaisonService;

    private final GzxAllocateRecordDbService allocateRecordDbService;

    private final GzxRegionDistrictListService regionDistrictListService;

    private final GzxProjectService projectService;

    private final UserCaffeine userCaffeine;

    private static final String MYSELF = "MYSELF";

    private static final String TASK_TITLE = "案件导入";
    private static final String WECHAT_CONTENT = "的案件导入任务";
    private static final String WECHAT_CONTENT2 = "条，耗时：";

    /**
     * 案件分页查询
     *
     * @param caseQueryBo
     * @return
     */
    @Override
    public Page<GzxCaseVo> pageList(GzxCaseQueryBo caseQueryBo) {
        LambdaQueryWrapper<GzxCase> lambdaQueryWrapper = buildQueryWrapper(caseQueryBo);
        Page<GzxCaseVo> result = caseDbService.pageList(new Page<>(caseQueryBo.getCurrent(), caseQueryBo.getSize()), lambdaQueryWrapper);
        if (CollectionUtil.isNotEmpty(result.getRecords())) {
            List<String> encryptCardIdList = result.getRecords().stream().map(caseVo -> CommonCryptogramUtil.doSm1AesEncrypt(caseVo.getDebtorCardId())).toList();
            List<GzxMediatorWorkVo> mediatorWorkVoList = mediatorWorkMapper.selectVoList(Wrappers.<GzxMediatorWork>lambdaQuery()
                    .select(GzxMediatorWork::getId)
                    .select(GzxMediatorWork::getDebtorCardId)
                    .in(GzxMediatorWork::getDebtorCardId, encryptCardIdList)
                    .gt(GzxMediatorWork::getCreateTime, CommonDateUtil.getTodayStr() + " 00:00:00")
                    .lt(GzxMediatorWork::getCreateTime, CommonDateUtil.getTodayStr() + " 23:59:59"));
            Set<String> debtorCardSet = mediatorWorkVoList.stream().map(GzxMediatorWorkVo::getDebtorCardId).collect(Collectors.toSet());
            if (MYSELF.equals(caseQueryBo.getPermissionType())) {
                result.getRecords().forEach(s -> {
                    if (debtorCardSet.contains(s.getDebtorCardId())) {
                        s.setIsTodayCall(1);
                    }
                });
            }
        }
        return result;
    }

    /**
     * 案件导入
     *
     * @param multipartFile
     * @param projectCode
     * @throws IOException
     */
    @Override
    public void importCase(MultipartFile multipartFile, String projectCode) {
        List<GzxCaseExcelVo> resultList = CommonExcelUtil.importExcel(multipartFile, GzxCaseExcelVo.class);
        if (CollectionUtil.isEmpty(resultList)) {
            throw new CommonException("Excel空");
        }
        SaBaseLoginUser loginUser = StpLoginUserUtil.getLoginUser();
        String tenantId = loginUser.getTenantId();
        String userId = loginUser.getId();
        String batchNumber = "EXCEL" + CommonBatchNumberUtil.getBatchNumber(BatchNumberConstant.CASE_BATCH_NUMBER);
        Date currentDate = new Date();
        //存储入库数据
        List<GzxCase> caseList = new ArrayList<>();
        List<GzxCaseDetail> caseDetailList = new ArrayList<>();
        List<GzxDebtorInfo> debtorInfoList = new ArrayList<>();
        List<GzxDebtorLiaison> debtorLiaisonList = new ArrayList<>();
        List<GzxAllocateRecord> allocateRecordList = new ArrayList<>();
        //存储异常信息
        Set<String> errorMessage = new HashSet<>();
        Set<String> noAccount = new HashSet<>();
        Set<String> projectError = new HashSet<>();
        Map<String, JSONObject> userMap = userCaffeine.getUserMap();
        Map<String, GzxProjectTileBo> projectTileBoMap = projectService.getProjectTile();
        Map<String, GzxRegionDistrict> regionDistrictMap = regionDistrictListService.getRegionDistrictList()
                .stream()
                .collect(Collectors.toMap(
                        s -> String.valueOf(s.getCode()),
                        Function.identity(),
                        (oldValue, newValue) -> newValue));
        log.info("{}案件导入---开始构建入库数据", loginUser.getName());
        CommonWechatUtil.sendMessage(TASK_TITLE + "【开始】", WechatNotificationType.TASK_START, List.of(loginUser.getEmpNo()), loginUser.getName() + WECHAT_CONTENT, "开始构建入库数据");
        for (int i = 0; i < resultList.size(); i++) {
            GzxCaseExcelVo caseExcelVo = resultList.get(i);
            String verifyCaseMsg = verifyCase(caseExcelVo);
            if (StringUtils.isNotBlank(verifyCaseMsg)) {
                errorMessage.add("第" + i + "行数据" + verifyCaseMsg);
                continue;
            }
            GzxCase gzxCase = new GzxCase();
            gzxCase.setBatchNumber(batchNumber);
            gzxCase.setProjectCode(projectCode);
            gzxCase.setTenantId(tenantId);
            gzxCase.setCreateUser(userId);
            gzxCase.setCreateTime(currentDate);
            String projectErrorMsg = setCaseProject(projectTileBoMap, gzxCase);
            if (StringUtils.isNotBlank(projectErrorMsg)) {
                projectError.add(projectErrorMsg);
                continue;
            }
            buildCaseInfo(gzxCase, caseExcelVo);
            //设置主表调解员
            if (StringUtils.isNotEmpty(caseExcelVo.getMediator())) {
                if (userMap.containsKey(caseExcelVo.getMediator())) {
                    JSONObject userJson = userMap.get(caseExcelVo.getMediator());
                    gzxCase.setCaseStatus(2);
                    gzxCase.setMediatorId(userJson.getLong("id"));
                    gzxCase.setMediatorName(userJson.getStr("name"));
                    gzxCase.setAffiliatedCompany(userJson.getLong("orgId"));
                    //组装分案数据
                    GzxAllocateRecord allocateRecord = new GzxAllocateRecord();
                    allocateRecord.setType(GzxAllocateType.ALLOCATE);
                    allocateRecord.setBatchNumber(batchNumber);
                    allocateRecord.setDebtorCardId(caseExcelVo.getDebtorCardId());
                    allocateRecord.setMediatorId(userJson.getLong("id"));
                    allocateRecord.setTenantId(tenantId);
                    allocateRecord.setCreateUser(userId);
                    allocateRecordList.add(allocateRecord);
                } else {
                    noAccount.add(caseExcelVo.getMediator());
                    continue;
                }
            }
            caseList.add(gzxCase);
            //组装明细数据
            GzxCaseDetail caseDetail = new GzxCaseDetail();
            caseDetail.setBatchNumber(batchNumber);
            caseDetail.setDebtorCardId(caseExcelVo.getDebtorCardId());
            caseDetail.setPartnerBusinessId(caseExcelVo.getPartnerBusinessId());
            caseDetail.setTenantId(tenantId);
            caseDetail.setCreateUser(userId);
            caseDetail.setContractNo(caseExcelVo.getContractNo());
            caseDetail.setLoanAmount(caseExcelVo.getLoanAmount());
            caseDetail.setOverdueAmount(caseExcelVo.getOverdueAmount());
            caseDetail.setOverdueDate(caseExcelVo.getOverdueDate());
            caseDetailList.add(caseDetail);
            //构建欠款人数据
            debtorInfoList.add(buildDebtorInfo(gzxCase, regionDistrictMap));
            //构建三方联系人数据
            debtorLiaisonList.add(buildDebtorLiaison(gzxCase));
        }
        List<GzxCase> mergeCaseList = mergeCasesByDebtorCardId(caseList);
        log.info("{}案件导入---数据构建完成，开始执行数据库写入", loginUser.getName());
        CommonWechatUtil.sendMessage(TASK_TITLE, WechatNotificationType.TASK_NOTICE, List.of(loginUser.getEmpNo()), loginUser.getName() + WECHAT_CONTENT, "数据构建完成，开始执行数据库写入");
        Thread.startVirtualThread(() -> {
            long caseStartTime = System.currentTimeMillis();
            try {
                TenantContext.disableTenantFilter();
                saveDbProcess(mergeCaseList, caseDetailList, debtorInfoList, debtorLiaisonList, allocateRecordList, loginUser);
            } catch (Exception e) {
                CommonWechatUtil.sendMessage(TASK_TITLE + "【异常】", WechatNotificationType.TASK_ERROR, List.of(loginUser.getEmpNo(), "ZhuJingTian-BeiJing"), loginUser.getName() + WECHAT_CONTENT, "数据写入异常，总耗时：" + (System.currentTimeMillis() - caseStartTime));
                log.error("{}案件导入---数据写入异常", loginUser.getName(), e);
            } finally {
                TenantContext.enableTenantFilter();
                TenantContext.clear();
                finallyErrorNotice(errorMessage, noAccount, projectError, loginUser);
                CommonWechatUtil.sendMessage(TASK_TITLE + "【结束】", WechatNotificationType.TASK_END, List.of(loginUser.getEmpNo()), loginUser.getName() + WECHAT_CONTENT, "数据写入完成，总耗时：" + (System.currentTimeMillis() - caseStartTime));
                log.info("{}案件导入---数据写入完成，总耗时：{}", loginUser.getName(), System.currentTimeMillis() - caseStartTime);
            }
        });
    }

    /**
     * 上下一案件
     *
     * @param changeCaseBo
     * @return
     */
    @Override
    public GzxCaseVo changeCase(GzxChangeCaseBo changeCaseBo) {
        LambdaQueryWrapper<GzxCase> lambdaQueryWrapper = new LambdaQueryWrapper<GzxCase>()
                .last("limit 1");
        lambdaQueryWrapper.ne(GzxCase::getId, changeCaseBo.getCaseId());
        if ("ascending".equals(changeCaseBo.getSort())) {
            if ("prev".equals(changeCaseBo.getType())) {
                lambdaQueryWrapper.lt(GzxCase::getCleanLoanAmount, changeCaseBo.getCleanLoanAmount());
                lambdaQueryWrapper.orderByDesc(GzxCase::getCleanLoanAmount);
            }
            if ("next".equals(changeCaseBo.getType())) {
                lambdaQueryWrapper.gt(GzxCase::getCleanLoanAmount, changeCaseBo.getCleanLoanAmount());
                lambdaQueryWrapper.orderByAsc(GzxCase::getCleanLoanAmount);
            }
        }
        if ("descending".equals(changeCaseBo.getSort())) {
            if ("prev".equals(changeCaseBo.getType())) {
                lambdaQueryWrapper.gt(GzxCase::getCleanLoanAmount, changeCaseBo.getCleanLoanAmount());
                lambdaQueryWrapper.orderByAsc(GzxCase::getCleanLoanAmount);
            }
            if ("next".equals(changeCaseBo.getType())) {
                lambdaQueryWrapper.lt(GzxCase::getCleanLoanAmount, changeCaseBo.getCleanLoanAmount());
                lambdaQueryWrapper.orderByDesc(GzxCase::getCleanLoanAmount);
            }
        }
        if (!StpLoginUserUtil.getLoginUser().getRoleCodeList().contains("superAdmin")) {
            lambdaQueryWrapper.eq(GzxCase::getMediatorId, StpLoginUserUtil.getLoginUser().getId());
            lambdaQueryWrapper.ge(GzxCase::getCreateTime, CommonDateUtil.getCurrentMonthFirstDay());
        }
        List<GzxCase> caseList = caseDbService.selectCaseList(lambdaQueryWrapper);
        if (CollectionUtil.isNotEmpty(caseList)) {
            return MapstructUtils.convert(caseList.getFirst(), GzxCaseVo.class);
        }
        return null;
    }

    /**
     * 查询案件明细
     *
     * @param caseDetailQueryBo
     * @return
     */
    @Override
    public Page<GzxCaseDetailVo> pageListDetail(GzxCaseDetailQueryBo caseDetailQueryBo) {
        return caseDbService.pageListDetail(new Page<>(caseDetailQueryBo.getCurrent(), caseDetailQueryBo.getSize()), Wrappers.<GzxCaseDetail>lambdaQuery()
                .eq(GzxCaseDetail::getBatchNumber, caseDetailQueryBo.getBatchNumber())
                .eq(GzxCaseDetail::getDebtorCardId, CommonCryptogramUtil.doSm1AesEncrypt(caseDetailQueryBo.getDebtorCardId()))
                .orderByDesc(GzxCaseDetail::getId));
    }

    /**
     * 查询案件详情JSON
     *
     * @param caseDetailId
     * @return
     */
    @Override
    public List<GzxCaseDetailJsonVo> getCaseDetailJson(Long caseDetailId) {
        List<GzxCaseDetail> caseDetailList = caseDbService.selectCaseDetailList(Wrappers.<GzxCaseDetail>lambdaQuery().eq(GzxCaseDetail::getId, caseDetailId));
        if (CollectionUtil.isNotEmpty(caseDetailList)) {
            return mapToList(JSON.parseObject(caseDetailList.getFirst().getAllDetail(), Map.class));
        }
        return List.of();
    }

    /**
     * 根据甲方系统主键获取案件详情
     *
     * @param parentBusinessId
     * @return
     */
    @Override
    public GzxCaseVo getCaseByParentBusinessId(String parentBusinessId) {
        List<GzxCaseDetail> caseDetailList = caseDbService.selectCaseDetailList(Wrappers.<GzxCaseDetail>lambdaQuery()
                .eq(GzxCaseDetail::getPartnerBusinessId, parentBusinessId).orderByDesc(GzxCaseDetail::getId));
        if (CollectionUtil.isEmpty(caseDetailList)) {
            throw new CommonException("根据甲方系统主键" + parentBusinessId + "匹配不到案件");
        }
        GzxCaseDetail caseDetail = caseDetailList.getFirst();
        return caseDbService.selectCaseVo(Wrappers.<GzxCase>lambdaQuery()
                .eq(GzxCase::getBatchNumber, caseDetail.getBatchNumber())
                .eq(GzxCase::getDebtorCardId, CommonCryptogramUtil.doSm1AesEncrypt(caseDetail.getDebtorCardId())));
    }

    /**
     * 案件修改
     *
     * @param caseEditBo
     */
    @Override
    public void update(GzxCaseEditBo caseEditBo) {
        caseDbService.updateById(MapstructUtils.convert(caseEditBo, GzxCase.class));
    }

    /**
     * 导出我的案件的联系人数据
     *
     * @param caseQueryBo
     * @param response
     */
    @Override
    public void exportMyCaseLiaison(GzxCaseQueryBo caseQueryBo, HttpServletResponse response) {
        caseQueryBo.setPermissionType(MYSELF);
        caseQueryBo.setSort("descending");
        String userName = StpLoginUserUtil.getLoginUser().getName();
        long caseTime = System.currentTimeMillis();
        log.info("{}：导出联系人----->查询我的案件-------------|开始", userName);
        List<GzxCaseVo> caseVoList = caseDbService.selectVoCaseList(buildQueryWrapper(caseQueryBo));
        if (CollectionUtil.isEmpty(caseVoList)) {
            throw new CommonException("无可导出的数据");
        }
        log.info("{}：导出联系人----->查询我的案件-------------|结束，耗时：{}", userName, System.currentTimeMillis() - caseTime);
        List<String> totalDebtorCardIdList = caseVoList.stream().map(caseVo -> CommonCryptogramUtil.doSm1AesEncrypt(caseVo.getDebtorCardId())).toList();
        log.info("{}：导出联系人----->查询黑名单用户-------------|开始", userName);
        long dataTime = System.currentTimeMillis();
        List<GzxComplaintUser> complaintUserList = complaintUserMapper.selectList(Wrappers.<GzxComplaintUser>lambdaQuery()
                .in(GzxComplaintUser::getIdCard, totalDebtorCardIdList));
        log.info("{}：导出联系人----->查询黑名单用户-------------|结束，耗时：{}", userName, System.currentTimeMillis() - dataTime);
        Set<String> blackDebtorCardIdList = complaintUserList.stream().map(GzxComplaintUser::getIdCard).collect(Collectors.toSet());
        List<GzxCaseVo> filteredList = caseVoList.stream().filter(createPredicate(blackDebtorCardIdList, GzxCaseVo::getDebtorCardId)).toList();
        Map<String, GzxCaseVo> caseVoMap = filteredList.stream().collect(Collectors.toMap(GzxCaseVo::getDebtorCardId, gzxCaseVo -> gzxCaseVo, (oldValue, newValue) -> newValue));
        List<List<GzxCaseVo>> batchList = Lists.partition(filteredList, 350);
        List<GzxDebtorLiaisonExcelVo> debtorLiaisonExcelVoList = new ArrayList<>();
        log.info("{}：导出联系人----->组织Excel数据-------------|开始", userName);
        long excelTime = System.currentTimeMillis();
        for (List<GzxCaseVo> batch : batchList) {
            List<String> debtorCardIdList = batch.stream().map(caseVo -> CommonCryptogramUtil.doSm1AesEncrypt(caseVo.getDebtorCardId())).toList();
            log.info("{}：导出联系人----->查询三方联系人-------------|开始", userName);
            long liaisonTime = System.currentTimeMillis();
            List<GzxDebtorLiaison> debtorLiaisonList = debtorLiaisonService.selectList(Wrappers.<GzxDebtorLiaison>lambdaQuery()
                    .in(GzxDebtorLiaison::getDebtorCardId, debtorCardIdList)
                    .apply("length(AES_DECRYPT(from_base64(liaison_phone), 'mhxzkhl@2024gzx.')) >= 7"));
            log.info("{}：导出联系人----->查询三方联系人-------------|结束，耗时：{}", userName, System.currentTimeMillis() - liaisonTime);
            log.info("{}：导出联系人----->手机号脱敏-------------|开始", userName);
            long sensitiveTime = System.currentTimeMillis();
            for (GzxDebtorLiaison debtorLiaison : debtorLiaisonList) {
                GzxDebtorLiaisonExcelVo debtorLiaisonExcelVo = new GzxDebtorLiaisonExcelVo();
                debtorLiaisonExcelVo.setPartnerBusinessId(caseVoMap.get(debtorLiaison.getDebtorCardId()).getPartnerBusinessId());
                debtorLiaisonExcelVo.setDebtorName(caseVoMap.get(debtorLiaison.getDebtorCardId()).getDebtorName());
                debtorLiaisonExcelVo.setRelationship(debtorLiaison.getRelationship());
                //欠款人手机号-密文
                debtorLiaisonExcelVo.setDebtorPhone(CommonCryptogramUtil.doSm1AesEncrypt(caseVoMap.get(debtorLiaison.getDebtorCardId()).getDebtorPhone()));
                debtorLiaisonExcelVo.setLiaisonName(debtorLiaison.getLiaisonName());
                //欠款人手机号-脱敏
                debtorLiaisonExcelVo.setSensitiveDebtorPhone(CommonSensitiveUtil.sensitivePhone(caseVoMap.get(debtorLiaison.getDebtorCardId()).getDebtorPhone()));
                //三方联系人手机号-密文
                debtorLiaisonExcelVo.setLiaisonPhone(CommonCryptogramUtil.doSm1AesEncrypt(debtorLiaison.getLiaisonPhone()));
                //三方联系人手机号-脱敏
                debtorLiaisonExcelVo.setSensitiveLiaisonPhone(CommonSensitiveUtil.sensitivePhone(debtorLiaison.getLiaisonPhone()));
                debtorLiaisonExcelVoList.add(debtorLiaisonExcelVo);
            }
            log.info("{}：导出联系人----->手机号脱敏-------------|结束，耗时：{}", userName, System.currentTimeMillis() - sensitiveTime);
        }
        log.info("{}：导出联系人----->组织Excel数据-------------|结束，耗时：{}", userName, System.currentTimeMillis() - excelTime);
        CommonExcelUtil.exportExcel("案件联系人", debtorLiaisonExcelVoList, GzxDebtorLiaisonExcelVo.class, response);
    }

    /**
     * 获取调解协议数据
     *
     * @param caseId
     * @return
     */
    @Override
    public GzxWordMediationVo getWordMediationData(Long caseId) {
        GzxWordMediationVo wordMediationVo = new GzxWordMediationVo();
        GzxCase gzxCase = caseDbService.selectCase(Wrappers.<GzxCase>lambdaQuery().eq(GzxCase::getId, caseId));
        wordMediationVo.setDebtorName(gzxCase.getDebtorName());
        wordMediationVo.setDebtorPhone(gzxCase.getDebtorPhone());
        wordMediationVo.setNoSensitiveDebtorPhone(gzxCase.getDebtorPhone());
        wordMediationVo.setDebtorCardId(gzxCase.getDebtorCardId());
        wordMediationVo.setNoSensitiveDebtorCardId(gzxCase.getDebtorCardId());
        wordMediationVo.setDebtorSex(String.valueOf(gzxCase.getDebtorSex()));
        wordMediationVo.setCaseId(String.valueOf(caseId));
        //查询案件详情
        List<GzxCaseDetail> caseDetailList = caseDbService.selectCaseDetailList(Wrappers.<GzxCaseDetail>lambdaQuery()
                .eq(GzxCaseDetail::getBatchNumber, gzxCase.getBatchNumber())
                .eq(GzxCaseDetail::getDebtorCardId, CommonCryptogramUtil.doSm1AesEncrypt(gzxCase.getDebtorCardId())));
        if (CollectionUtil.isNotEmpty(caseDetailList) && caseDetailList.size() == 1) {
            GzxCaseDetail caseDetail = caseDetailList.getFirst();
            wordMediationVo.setDebtorClientId(caseDetail.getPartnerBusinessId());
            wordMediationVo.setContractNo(caseDetail.getContractNo());
            wordMediationVo.setContractStartDate(caseDetail.getLoanDate());
//            wordMediationAddBo.setOverdueAmount(caseDetail.getOverdueAmount());
//            if (StringUtils.isNotBlank(caseDetail.getOverdueDate())) {
//                wordMediationAddBo.setOverdueDays(CommonDateUtil.getDifferDay(caseDetail.getOverdueDate()));
//            }
        }
        return wordMediationVo;
    }

    private LambdaQueryWrapper<GzxCase> buildQueryWrapper(GzxCaseQueryBo bo) {
        LambdaQueryWrapper<GzxCase> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getCompanyCode()), GzxCase::getCompanyCode, bo.getCompanyCode());
        lqw.eq(StringUtils.isNotBlank(bo.getProductCode()), GzxCase::getProductCode, bo.getProductCode());
        lqw.eq(StringUtils.isNotBlank(bo.getProjectCode()), GzxCase::getProjectCode, bo.getProjectCode());
        lqw.eq(StringUtils.isNotBlank(bo.getBatchNumber()), GzxCase::getBatchNumber, bo.getBatchNumber());
        lqw.eq(StringUtils.isNotBlank(bo.getMediatorName()), GzxCase::getMediatorName, bo.getMediatorName());
        lqw.eq(bo.getCaseStatus() != null, GzxCase::getCaseStatus, bo.getCaseStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getDebtorName()), GzxCase::getDebtorName, bo.getDebtorName());
        lqw.eq(bo.getIntentTag() != null, GzxCase::getIntentTag, bo.getIntentTag());
        lqw.eq(StringUtils.isNotBlank(bo.getDebtorPhone()), GzxCase::getDebtorPhone, CommonCryptogramUtil.doSm1AesEncrypt(bo.getDebtorPhone()));
        if (MYSELF.equals(bo.getPermissionType())) {
            lqw.ge(GzxCase::getCreateTime, CommonDateUtil.getCurrentMonthFirstDay());
            lqw.eq(GzxCase::getMediatorId, StpUtil.getLoginId());
            if ("descending".equals(bo.getSort())) {
                lqw.orderByDesc(GzxCase::getCleanLoanAmount);
            }
            if ("ascending".equals(bo.getSort())) {
                lqw.orderByAsc(GzxCase::getCleanLoanAmount);
            }
        }
        lqw.orderByDesc(GzxCase::getId);
        if ("ALL".equals(bo.getPermissionType())) {
            lqw.ge(GzxCase::getCreateTime, "2024-09-01");
        }
        if (StringUtils.isNotBlank(bo.getPartnerBusinessId())) {
            List<GzxCaseDetail> caseDetailList = caseDbService.selectCaseDetailList(Wrappers.<GzxCaseDetail>lambdaQuery()
                    .select(GzxCaseDetail::getDebtorCardId, GzxCaseDetail::getBatchNumber)
                    .eq(GzxCaseDetail::getPartnerBusinessId, bo.getPartnerBusinessId())
                    .orderByDesc(GzxCaseDetail::getId)
                    .last("limit 1"));
            String debtorCardId = "111";
            String batchNumber = "111";
            if (CollectionUtil.isNotEmpty(caseDetailList)) {
                GzxCaseDetail caseDetail = caseDetailList.get(0);
                debtorCardId = CommonCryptogramUtil.doSm1AesEncrypt(caseDetail.getDebtorCardId());
                batchNumber = caseDetail.getBatchNumber();
            }
            lqw.eq(GzxCase::getDebtorCardId, debtorCardId);
            lqw.eq(GzxCase::getBatchNumber, batchNumber);
        }
        return lqw;
    }

    private List<GzxCaseDetailJsonVo> mapToList(Map<String, Object> jsonMap) {
        Map<String, String> dictMap = new HashMap<>();
        dictMap.put("bankName", "银行名称");
        dictMap.put("productName", "产品名称");
        dictMap.put("idNo", "身份证号");
        dictMap.put("residAddress", "身份证地址");
        dictMap.put("contractNo", "合同号");
        dictMap.put("contractDate", "合同日期");
        dictMap.put("lendingSide", "放款方");
        dictMap.put(" businessId", "甲方系统唯一ID");
        dictMap.put(" orderStatus", "订单状态");
        dictMap.put(" outOverPeriod", "逾期天数");
        dictMap.put(" registrationDate", "注册日期");
        dictMap.put(" currentPenalty", "罚息利率");
        dictMap.put(" deliveryDate", "放款日期");
        dictMap.put(" overdueTotalAmount", "逾期总金额");
        dictMap.put(" outPeriod", "已出期数");
        dictMap.put("resAddress", "联系地址");
        dictMap.put("overdueDate", "逾期日期");
        dictMap.put("bankCardNo", "收款卡号");
        dictMap.put("billDay", "账单日");
        dictMap.put("guaranteeName", "担保方");
        dictMap.put("sex", "性别");
        dictMap.put("cleanLoanTotalAmount", "清贷总金额");
        dictMap.put("contractPenalty", "合同利率");
        dictMap.put("custName", "客户姓名");
        dictMap.put(" serviceName", "服务方");
        dictMap.put(" coYearRate", "合同综合费率(年)");
        dictMap.put(" repaymentMode", "还款方式");
        dictMap.put(" loanAmount", "放贷金额");
        dictMap.put("phone", "手机号");
        dictMap.put("supportPublic", "是否支持对公还款");
        dictMap.put("loanPeriod", "贷款期数");
        List<GzxCaseDetailJsonVo> mapVoList = new ArrayList<>();
        int num = 0;
        GzxCaseDetailJsonVo mapVo = null;
        if (CollectionUtil.isNotEmpty(jsonMap)) {
            for (Map.Entry<String, Object> entry : jsonMap.entrySet()) {
                num++;
                String key = entry.getKey();
                if (dictMap.containsKey(key)) {
                    key = dictMap.get(key);
                }
                key += ":";
                String value = String.valueOf(entry.getValue());
                if (num == 1) {
                    mapVo = new GzxCaseDetailJsonVo();
                    mapVo.setKey1(key);
                    mapVo.setKey2(value);
                } else {
                    mapVo.setKey3(key);
                    mapVo.setKey4(value);
                    mapVoList.add(mapVo);
                    num = 0;
                }
            }
        }
        return mapVoList;
    }

    private static <T> Predicate<T> createPredicate(Set<String> valuesToRemove, Function<? super T, ? extends String> fieldGetter) {
        return obj -> !valuesToRemove.contains(fieldGetter.apply(obj));
    }

    private String verifyCase(GzxCaseExcelVo caseExcelVo) {
        if (caseExcelVo.getLoanAmount() == null && caseExcelVo.getOverdueAmount() == null) {
            return "放款金额和逾期金额不能都为空";
        }
        String debtorCardId = caseExcelVo.getDebtorCardId();
        if (StringUtils.isEmpty(debtorCardId)) {
            return "身份证号为空";
        }
        return null;
    }

    private String setCaseProject(Map<String, GzxProjectTileBo> projectTileBoMap, GzxCase gzxCase) {
        String projectCode = gzxCase.getProjectCode();
        String errorMsg = null;
        if (projectTileBoMap.containsKey(projectCode)) {
            GzxProjectTileBo projectTileBo = projectTileBoMap.get(projectCode);
            if (StringUtils.isNotBlank(projectTileBo.getProductCode())) {
                gzxCase.setProductCode(projectTileBo.getProductCode());
            } else {
                errorMsg = projectCode + "匹配不到对应的产品";
            }
            if (StringUtils.isNotBlank(projectTileBo.getCompanyCode())) {
                gzxCase.setCompanyCode(projectTileBo.getCompanyCode());
            } else {
                errorMsg = projectCode + "匹配不到对应的委托公司";
            }
        } else {
            errorMsg = projectCode + "不存在";
        }
        return errorMsg;
    }

    private void buildCaseInfo(GzxCase gzxCase, GzxCaseExcelVo caseExcelVo) {
        gzxCase.setCaseStatus(1);
        gzxCase.setDebtorName(caseExcelVo.getDebtorName());
        gzxCase.setDebtorPhone(caseExcelVo.getDebtorPhone());
        gzxCase.setDebtorSex(CommonCardIDUtil.getSexByIdCard(caseExcelVo.getDebtorCardId()));
        gzxCase.setDebtorCardId(caseExcelVo.getDebtorCardId());
        gzxCase.setLoanAmount(caseExcelVo.getLoanAmount());
        gzxCase.setOverdueAmount(caseExcelVo.getOverdueAmount());
        gzxCase.setOverdueStatus(1);
        gzxCase.setCleanLoanAmount(gzxCase.getOverdueAmount());
        gzxCase.setPartnerBusinessId(caseExcelVo.getPartnerBusinessId());
    }

    private GzxDebtorInfo buildDebtorInfo(GzxCase gzxCase, Map<String, GzxRegionDistrict> regionDistrictMap) {
        GzxDebtorInfo debtorInfo = new GzxDebtorInfo();
        debtorInfo.setDebtorName(gzxCase.getDebtorName());
        debtorInfo.setDebtorPhone(gzxCase.getDebtorPhone());
        debtorInfo.setDebtorCardId(gzxCase.getDebtorCardId());
        debtorInfo.setProjectCode(gzxCase.getProjectCode());
        //获取身份证号省市，性别
        try {
            String debtorCardId = gzxCase.getDebtorCardId();
            String position = StringUtils.isEmpty(debtorCardId) && IdcardUtil.isValidCard18(debtorCardId) ? "" : debtorCardId.substring(0, 6);
            if (regionDistrictMap.containsKey(position)) {
                debtorInfo.setDebtorProvince(regionDistrictMap.get(position).getProvince());
                debtorInfo.setDebtorCity(regionDistrictMap.get(position).getCity());
                debtorInfo.setDebtorAge(CommonCardIDUtil.getAgeByIdCard(gzxCase.getDebtorCardId()));
            }
        } catch (Exception e) {
            log.error("解析身份证号出错", e);
        }
        debtorInfo.setDebtorSex(gzxCase.getDebtorSex());
        debtorInfo.setTenantId(gzxCase.getTenantId());
        debtorInfo.setCreateUser(gzxCase.getCreateUser());
        return debtorInfo;
    }

    private GzxDebtorLiaison buildDebtorLiaison(GzxCase gzxCase) {
        GzxDebtorLiaison debtorLiaison = new GzxDebtorLiaison();
        debtorLiaison.setDebtorCardId(gzxCase.getDebtorCardId());
        debtorLiaison.setLiaisonName(gzxCase.getDebtorName());
        debtorLiaison.setLiaisonPhone(gzxCase.getDebtorPhone());
        debtorLiaison.setCallRecipient(1);
        debtorLiaison.setRelationship("本人");
        debtorLiaison.setPhoneSource(1);
        debtorLiaison.setTenantId(gzxCase.getTenantId());
        debtorLiaison.setCreateUser(gzxCase.getCreateUser());
        debtorLiaison.setProjectCode(gzxCase.getProjectCode());
        return debtorLiaison;
    }

    public static List<GzxCase> mergeCasesByDebtorCardId(List<GzxCase> caseList) {
        return caseList.stream()
                .collect(Collectors.toMap(
                        GzxCase::getDebtorCardId,
                        caseItem -> {
                            GzxCase newCase = new GzxCase();
                            BeanUtils.copyProperties(caseItem, newCase);
                            return newCase;
                        },
                        (case1, case2) -> {
                            // 金额累加逻辑
                            case1.setLoanAmount(case1.getLoanAmount().add(case2.getLoanAmount()));
                            case1.setOverdueAmount(case1.getOverdueAmount().add(case2.getOverdueAmount()));
                            return case1;
                        }
                ))
                .values().stream()
                .peek(caseItem -> caseItem.setCleanLoanAmount(caseItem.getOverdueAmount()))
                .toList();
    }

    private void saveDbProcess(List<GzxCase> caseList,
                               List<GzxCaseDetail> caseDetailList,
                               List<GzxDebtorInfo> debtorInfoList,
                               List<GzxDebtorLiaison> debtorLiaisonList,
                               List<GzxAllocateRecord> allocateRecordList,
                               SaBaseLoginUser loginUser) {
        long caseStartTime = System.currentTimeMillis();
        caseDbService.saveBatch(caseList);
        CommonWechatUtil.sendMessage(TASK_TITLE, WechatNotificationType.TASK_NOTICE, List.of(loginUser.getEmpNo()), loginUser.getName() + WECHAT_CONTENT, "案件主表数据写入完成，共计" + caseList.size() + WECHAT_CONTENT2 + (System.currentTimeMillis() - caseStartTime));
        log.info("{}案件导入---案件主表数据写入完成，共计{}{}{}", loginUser.getName(), caseList.size(), WECHAT_CONTENT2, System.currentTimeMillis() - caseStartTime);

        long caseDetailStartTime = System.currentTimeMillis();
        caseDbService.saveBatchDetail(caseDetailList);
        CommonWechatUtil.sendMessage(TASK_TITLE, WechatNotificationType.TASK_NOTICE, List.of(loginUser.getEmpNo()), loginUser.getName() + WECHAT_CONTENT, "案件明细数据写入完成，共计" + caseDetailList.size() + WECHAT_CONTENT2 + (System.currentTimeMillis() - caseDetailStartTime));
        log.info("{}案件导入---案件明细数据写入完成，共计{}{}{}", loginUser.getName(), caseDetailList.size(), WECHAT_CONTENT2, System.currentTimeMillis() - caseDetailStartTime);

        long debtorStartTime = System.currentTimeMillis();
        debtorInfoService.insertBatch(debtorInfoList);
        CommonWechatUtil.sendMessage(TASK_TITLE, WechatNotificationType.TASK_NOTICE, List.of(loginUser.getEmpNo()), loginUser.getName() + WECHAT_CONTENT, "欠款人信息数据写入完成，共计" + debtorInfoList.size() + WECHAT_CONTENT2 + (System.currentTimeMillis() - debtorStartTime));
        log.info("{}案件导入---欠款人信息数据写入完成，共计{}{}{}", loginUser.getName(), debtorInfoList.size(), WECHAT_CONTENT2, System.currentTimeMillis() - debtorStartTime);

        long liaisonStartTime = System.currentTimeMillis();
        debtorLiaisonService.insertBatch(debtorLiaisonList);
        CommonWechatUtil.sendMessage(TASK_TITLE, WechatNotificationType.TASK_NOTICE, List.of(loginUser.getEmpNo()), loginUser.getName() + WECHAT_CONTENT, "三方联系人数据写入完成，共计" + debtorLiaisonList.size() + WECHAT_CONTENT2 + (System.currentTimeMillis() - liaisonStartTime));
        log.info("{}案件导入---三方联系人数据写入完成，共计{}{}{}", loginUser.getName(), debtorLiaisonList.size(), WECHAT_CONTENT2, System.currentTimeMillis() - liaisonStartTime);

        if (CollectionUtil.isNotEmpty(allocateRecordList)) {
            long allocateStartTime = System.currentTimeMillis();
            allocateRecordDbService.saveBatch(allocateRecordList);
            CommonWechatUtil.sendMessage(TASK_TITLE, WechatNotificationType.TASK_NOTICE, List.of(loginUser.getEmpNo()), loginUser.getName() + WECHAT_CONTENT, "分案数据写入完成，共计" + allocateRecordList.size() + WECHAT_CONTENT2 + (System.currentTimeMillis() - allocateStartTime));
            log.info("{}案件导入---分案数据写入完成，共计{}{}{}", loginUser.getName(), allocateRecordList.size(), WECHAT_CONTENT2, System.currentTimeMillis() - allocateStartTime);
        }
    }

    private void finallyErrorNotice(Set<String> errorMessage, Set<String> noAccount, Set<String> projectError, SaBaseLoginUser loginUser) {
        if (CollectionUtil.isNotEmpty(errorMessage)) {
            CommonWechatUtil.sendMessage(TASK_TITLE + "【异常】", WechatNotificationType.TASK_ERROR, List.of(loginUser.getEmpNo()), errorMessage.toArray(new String[0]));
        }
        if (CollectionUtil.isNotEmpty(noAccount)) {
            CommonWechatUtil.sendMessage(TASK_TITLE + "【异常】", WechatNotificationType.TASK_ERROR, List.of(loginUser.getEmpNo()), noAccount + "---以上账号因在自研系统匹配不到，分案失败，其余调解员的案件正常分配并结束");
        }
        if (CollectionUtil.isNotEmpty(projectError)) {
            CommonWechatUtil.sendMessage(TASK_TITLE + "【异常】", WechatNotificationType.TASK_ERROR, List.of(loginUser.getEmpNo()), projectError.toString());
        }
    }
}
